#include "gdcmqt.h"
#include <gdcmImageReader.h>

bool GDCMQT::ConvertToFormat_RGB888(const gdcm::Image & gimage, char * buffer, QImage *& imageQt) {
  qDebug() << "This image has " << gimage.GetNumberOfDimensions() << " dimensions;";
  unsigned int dimX = gimage.GetDimension(0);
  unsigned int dimY = gimage.GetDimension(1);
  qDebug() << "Image size is " << dimX << " x " << dimY;

  gimage.GetBuffer(buffer);

  // Let's start with the easy case:
  if( gimage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB ) {
    qDebug() << "RGB";
    if( gimage.GetPixelFormat() != gdcm::PixelFormat::UINT8 ) {
      return false;
    }
    unsigned char *ubuffer = (unsigned char*)buffer;
    // QImage::Format_RGB888  13  The image is stored using a 24-bit RGB format (8-8-8).
    imageQt = new QImage((unsigned char *)ubuffer, dimX, dimY, 3*dimX, QImage::Format_RGB888);
  } else if( gimage.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 ) {
    qDebug() << "MONO2";
    if( gimage.GetPixelFormat() == gdcm::PixelFormat::UINT8 ) {
      qDebug() << "UINT8";
      // We need to copy each individual 8bits into R / G and B:
      unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
      unsigned char *pubuffer = ubuffer;
      for(unsigned int i = 0; i < dimX*dimY; i++) {
        *pubuffer++ = *buffer;
        *pubuffer++ = *buffer;
        *pubuffer++ = *buffer++;
      }
      imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
    } else if( gimage.GetPixelFormat() == gdcm::PixelFormat::INT16 ) {
      qDebug() << "INT16";
      // We need to copy each individual 16bits into R / G and B (truncate value)
      short *buffer16 = (short*)buffer;
      unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
      unsigned char *pubuffer = ubuffer;
      for(unsigned int i = 0; i < dimX*dimY; i++) {
        // Scalar Range of gdcmData/012345.002.050.dcm is [0,192], we could simply do:
        // *pubuffer++ = *buffer16;
        // *pubuffer++ = *buffer16;
        // *pubuffer++ = *buffer16;
        // instead do it right:
        *pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255);
        *pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255);
        *pubuffer++ = (unsigned char)std::min(255, (32768 + *buffer16) / 255);
        buffer16++;
      }

      imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
    } else if( gimage.GetPixelFormat() == gdcm::PixelFormat::UINT16 ) {
      qDebug() << "UINT16";
      // We need to copy each individual 16bits into R / G and B (truncate value)
      short *buffer16 = (short*)buffer;
      unsigned char *ubuffer = new unsigned char[dimX*dimY*3];
      unsigned char *pubuffer = ubuffer;
//      gimage.GetNumberOfDimensions()
//      const double factor = 65535.0/255.0;
      short max = 0;
      for(unsigned int i = 0; i < dimX*dimY; i++) {
        max = std::max(*buffer16, max);
        buffer16++;
      }
      buffer16 = (short*)buffer;

      qDebug() << "Maximum: " << max;
      const double factor = (double)(max)/255.0;
      for(unsigned int i = 0; i < dimX*dimY; i++) {
        // Scalar Range of gdcmData/012345.002.050.dcm is [0,192], we could simply do:
        // *pubuffer++ = *buffer16;
        // *pubuffer++ = *buffer16;
        // *pubuffer++ = *buffer16;
        // instead do it right:
        unsigned char pixel = static_cast<unsigned char>( static_cast<double>(*buffer16) / factor );
        *pubuffer++ = pixel;
        *pubuffer++ = pixel;
        *pubuffer++ = pixel;
        buffer16++;
      }

      imageQt = new QImage(ubuffer, dimX, dimY, QImage::Format_RGB888);
    } else {
      qDebug() << "Some other type";
      qDebug() << "Format is: " << gimage.GetPixelFormat();
      std::cerr << "Pixel Format is: " << gimage.GetPixelFormat() << std::endl;
      return false;
    }
  } else {
    std::cerr << "Unhandled PhotometricInterpretation: " << gimage.GetPhotometricInterpretation() << std::endl;
    return false;
  }

  return true;
}
